import os
import sys
import re
import datetime as dt
import logging
from os.path import join
import cgi

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
#from google.appengine.ext.webapp import template
from mako.template import Template
from mako.lookup import TemplateLookup
_tmpllookup = None
from google.appengine.api import users
from google.appengine.ext.webapp import RequestHandler

re_date = re.compile( "^([0-9]{4})-([0-9]{2})-([0-9]{2})$" )
re_datetime = re.compile( "^([0-9]{4})-([0-9]{2})-([0-9]{2})\s+([0-9]+):([0-9]+)$" )
re_datetimesec = re.compile( "^([0-9]{4})-([0-9]{2})-([0-9]{2})\s+([0-9]+):([0-9]+):([0-9]+)$" )
log = logging.getLogger(__name__)
class GCWebApp(webapp.WSGIApplication):
    
    def __init__(self, url_mapping, debug=True):
    
        webapp.WSGIApplication.__init__(self, url_mapping, debug )
    
    def add_handler( self, regexp, handler ):
        
      self._handler_map[handler.__name__] = handler

      if not regexp.startswith('^'):
        regexp = '^' + regexp
      if not regexp.endswith('$'):
        regexp += '$'

      compiled = re.compile(regexp)
      self._url_mapping.append((compiled, handler))

      num_groups = len(webapp.RE_FIND_GROUPS.findall(regexp))
      handler_patterns = self._pattern_map.setdefault(handler, [])
      handler_patterns.append((compiled, num_groups))

        



_application = GCWebApp([], debug=True)
                                     
def user():
    
    return users.get_current_user()

def app():
    
    return _application

_templatepath = None

def setTemplatePath( path ):
    
    global _templatepath
    global _tmpllookup
    if( path == None or not os.path.exists( path ) ):
        raise Exception, "%s is either empty or not exists!" % path

    _templatepath = path

    _tmpllookup = TemplateLookup(directories=[_templatepath], default_filters=['ctx.h.enc'])

_gmapkey = None

def setGMapKey( key ):
    global _gmapkey
    _gmapkey = key

class helper():
    def hidemail(self,text):
        
        user = text
        host = None

        m = re.search( "(.*)@(.*)", text )
        
        if( m != None ):
            user = m.group(1)
            host = m.group(2)
            
            if( user > 3 ):
                user = user[0:2]
            else:
                if ( user > 2 ):
                    user = user[0:1]
                    
            user += "..."        
            
            out = user
            if( host and host != "" ):
                out += " from %s " % host
                
            return out
        
    def loginurl(self,uri):
        return users.create_login_url(uri)
    def textcut(self, text, length, moreurl):
        
        out = ""
        if( text == None ):
            out =  ""
        else:
            if( len(out) > length ):
                out = text[0:len-1]
            else:
                out = text
        
        out = self.replws(cgi.escape(out,True))
        
        if( None != text and len(text) > length ):
            out += "<br>"
            out += "<a href='%s'>Read more</a>" % moreurl
        
        return out
        
        
    def default(self,text,default):
        if( text == None ): return default
        return text
    def enc(self,text):
        return unicode(text)
        #return text
    def replws(self,text):
        log.debug( text )
        text = text.replace( "\n", "<br>" )
        text = text.replace( "     ", "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" )
        text = text.replace( "    ", "&nbsp;&nbsp;&nbsp;&nbsp;" )
        text = text.replace( "   ", "&nbsp;&nbsp;&nbsp;" )
        text = text.replace( "  ", "&nbsp;&nbsp;" )
        
        text = text.replace( "\t", "&nbsp;&nbsp;&nbsp;&nbsp;" )
        log.debug( text )
        return text
    def defnone(self,text ):
        
        if( text == None ):
            return ""
        if( text == "None" ):
            return ""
        else:
            return text
        
    def input_date( self, name, value = "",id="",  style=""):
        
        return """
<SCRIPT LANGUAGE="JavaScript" ID="js1">
var calendar = new CalendarPopup();
</SCRIPT>
<INPUT TYPE="text" NAME="%(name)s" VALUE="%(value)s" SIZE=25 ID="%(id)s" style="%(style)s">
<A HREF="#" 
    onClick="calendar.select(document.forms[0].%(name)s,'anchor1_%(name)s','yyyy-MM-dd'); return false;" 
    NAME="anchor1_%(name)s" ID="anchor1_%(name)s">select</A>
            """ % { "name":name, "value":value, "style":style, "id":id }

class render_context():
    
    class Required():
        def get(self, key):
            try:
                return self.key
            except:
                return False
        pass
    
    def __init__(self):    
        self.req = self.Required()
        self.edit = False
        self.msg = {}
        self.errors = False
        self.gmapkey = _gmapkey
        self.h = helper()
    pass
    
    

def render( path, ctx ):
    
    if( _templatepath == None ):
        raise Exception, "template path is not set!"
    """    
    if( None == re.search( "^/", path ) ):
        path = "/" + path
    path = _templatepath + path
    path = os.path.normcase( path )
    if( not os.path.exists( path ) ):
        raise Exception, "template %s does not exists!" % path 
        
    basehtml = _templatepath + "/en/base.html"
    """
    basehtml = "/en/base.html"
    template = _tmpllookup.get_template( path )
    
    rend_params = { "ctx":ctx, "h":helper() }    
    return template.render_unicode( **rend_params ).encode("utf-8")   
    
class MJRequestHandler(RequestHandler):

    user_required = True
    path = None

    handlers = {}

    def render( self, template ):
        
        return render( template, self.c )

    def __init__(self):

        RequestHandler.__init__(self)
        
        if( self.path == None ):
            raise Exception, "Could not instantiate class without path set!"
        
        self.user = user()
        self.is_admin = users.is_current_user_admin()
        
        self.c = render_context()
        self.c.user = self.user
        self.c.is_admin = users.is_current_user_admin()
    def index(self):
        
        self.response.out.write( "Hello World" )
    
    class Handler():
        
        def __init__(self, path, handler, user_required = True):
            self.handler = handler
            self.path = path
            self.user_required = user_required
        
            log.debug( "Handler.user_required = %s" % self.user_required )
        def __call__(self):
            
            return self.handler()
                
    def add_handler(self, path, handler, user_required = True ):
        
        self.handlers[path] = self.Handler( path, handler, user_required )
        
    def to_date( self, string, name ):
        out = None
        log.debug( "got date as %s" % string )
        if( string != None and string != "" ):
            m = re_date.match( string.strip() )
            if( m == None ):
                self.c.errors = True
                self.c.msg[name] = "should have format YYYY-MM-DD"
            else:
                try:
                    out = dt.date( int(m.group(1)), int(m.group(2)), int(m.group(3)) )
                except Exception, e:
                    self.c.errors = True
                    self.c.msg[name] = e
                    
        log.debug( "return date as %s" % out )
        return out            

    def to_datetime( self, string, name ):
        out = None
        log.debug( "got date as %s" % string )
        if( string != None and string != "" ):
            m = re_datetimesec.match( string.strip() )
            if( m == None ):
                    
                m = re_datetime.match( string.strip() )
                if( m == None ):
                    log.debug( "seems to be not a datetime, try as date" )
                    m = re_date.match( string.strip() )
                        
                    if( m == None ):
                        self.c.errors = True
                        self.c.msg[name] = "should have format YYYY-MM-DD HH:MM"
                    else:
                        try:
                            out = dt.datetime( int(m.group(1)), int(m.group(2)), int(m.group(3)) )
                        except Exception, e:
                            self.c.errors = True
                            self.c.msg[name] = e
                else: 
                    try:
                        out = dt.datetime( int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4)), int(m.group(5)) )
                    except Exception, e:
                        self.c.errors = True
                        self.c.msg[name] = e
            else:
                try:
                    out = dt.datetime( \
                        int(m.group(1)), \
                        int(m.group(2)), \
                        int(m.group(3)), \
                        int(m.group(4)), \
                        int(m.group(5)), \
                        int(m.group(6)) )
                except Exception, e:
                    self.c.errors = True
                    self.c.msg[name] = e
                    
        log.debug( "return date as %s" % out )
        return out            


    def handle(self):
                
        for p in self.handlers:
            
            hpath = self.path
            
            if( not p.startswith( "/" ) ):
                hpath += "/" 
            
            hpath += p
            log.debug( "check path %s vs. %s" % ( self.request.path, hpath ) )
            if( self.request.path.startswith(hpath) ):
 
                if( self.handlers[p].user_required  and self.user == None ):
                    self.redirect(users.create_login_url(self.request.uri))
                    return
                try:    
                    out = self.handlers[p]()
                except:
                    self.redirect( "/error?msg=Unexpected error!" )
                    log.exception( "Unexpected error" )
                    return
                
                if( out != None ):
                    log.debug( "write output" )
                    self.response.out.write(out)
                log.debug( "return" )    
                return
                
        log.debug( "no handler found, try index" )

        # check global user requirement for that controller
        if( self.user_required  and self.user == None ):
            self.redirect(users.create_login_url(self.request.uri))
            return
#        log.debug( "%s" % self.index )
        out = self.index()
        if( out != None ):
            self.response.out.write(out)

    def get(self):
        self.handle()

    def post(self):
        self.handle()
        
    def redirect_index(self):
        return self.redirect( self.path )    

def check_admin( method ):
    
    def wrapper( self ):
        
        if( not self.is_admin ):
            log.debug( "check_admin: admin rights are missing" )
            
            return self.render( "/en/adminrequired.html" )
        else:
            return method( self )
    
    return wrapper
